Imports Microsoft.VisualBasic
Imports System
Imports System.Collections
Imports System.Drawing
Imports System.Drawing.Text
Imports System.Drawing.Drawing2D
Imports System.ComponentModel
Imports System.Windows.Forms
Imports Phoenix.Tools.Win32


Namespace Phoenix.Tools.General
  #Region "3D Styles Enums"
  Public Enum Canvas3DStyle
	[Single]
	Raised
	Upped
	Title
	Flat
  End Enum

  Public Enum HightlightStyle
	Active
	Selected
  End Enum
  #End Region

  Public NotInheritable Class GDIUtils
#Region "Class Members"
        Private Shared format As StringFormat = New StringFormat

        ' store brushes to optimize memory managment
        Private m_brushDark As SolidBrush = Nothing
        Private m_brushDarkDark As SolidBrush = Nothing
        Private m_brushLight As SolidBrush = Nothing
        Private m_brushLightLight As SolidBrush = Nothing

        ' colors on which brushes are based
        Private m_clrDark As Color
        Private m_clrDarkDark As Color
        Private m_clrLight As Color
        Private m_clrLightLight As Color

        ' pens used by class for drawing
        Private m_penDark As Pen = Nothing
        Private m_penDarkDark As Pen = Nothing
        Private m_penLight As Pen = Nothing
        Private m_penLightLight As Pen = Nothing
#End Region

#Region "Class Properties"
        Public Property Dark() As Color
            Get
                Return m_clrDark
            End Get
            Set(ByVal Value As Color)
                If Value.Equals(m_clrDark) Then
                    Return
                End If
                m_clrDark = Value

                ' destoroy old values
                If Not m_brushDark Is Nothing Then
                    m_brushDark.Dispose()
                End If
                If Not m_penDark Is Nothing Then
                    m_penDark.Dispose()
                End If

                m_brushDark = New SolidBrush(m_clrDark)
                m_penDark = New Pen(m_brushDark)
            End Set
        End Property
        Public Property DarkDark() As Color
            Get
                Return m_clrDarkDark
            End Get
            Set(ByVal Value As Color)
                If Value.Equals(m_clrDarkDark) Then
                    Return
                End If
                m_clrDarkDark = Value

                ' destoroy old values
                If Not m_brushDarkDark Is Nothing Then
                    m_brushDarkDark.Dispose()
                End If
                If Not m_penDarkDark Is Nothing Then
                    m_penDarkDark.Dispose()
                End If

                m_brushDarkDark = New SolidBrush(m_clrDarkDark)
                m_penDarkDark = New Pen(m_brushDarkDark)
            End Set
        End Property
        Public Property Light() As Color
            Get
                Return m_clrLight
            End Get
            Set(ByVal Value As Color)
                If Value.Equals(m_clrLight) Then
                    Return
                End If
                m_clrLight = Value

                ' destoroy old values
                If Not m_brushLight Is Nothing Then
                    m_brushLight.Dispose()
                End If
                If Not m_penLight Is Nothing Then
                    m_penLight.Dispose()
                End If

                m_brushLight = New SolidBrush(m_clrLight)
                m_penLight = New Pen(m_brushLight)
            End Set
        End Property
        Public Property LightLight() As Color
            Get
                Return m_clrLightLight
            End Get
            Set(ByVal Value As Color)
                If Value.Equals(m_clrLightLight) Then
                    Return
                End If
                m_clrLightLight = Value

                ' destoroy old values
                If Not m_brushLightLight Is Nothing Then
                    m_brushLightLight.Dispose()
                End If
                If Not m_penLightLight Is Nothing Then
                    m_penLightLight.Dispose()
                End If

                m_brushLightLight = New SolidBrush(m_clrLightLight)
                m_penLightLight = New Pen(m_brushLightLight)
            End Set
        End Property


        Public ReadOnly Property DarkBrush() As Brush
            Get
                Return m_brushDark
            End Get
        End Property
        Public ReadOnly Property DarkDarkBrush() As Brush
            Get
                Return m_brushDarkDark
            End Get
        End Property
        Public ReadOnly Property LightBrush() As Brush
            Get
                Return m_brushLight
            End Get
        End Property
        Public ReadOnly Property LightLightBrush() As Brush
            Get
                Return m_brushLightLight
            End Get
        End Property


        Public ReadOnly Property DarkPen() As Pen
            Get
                Return m_penDark
            End Get
        End Property
        Public ReadOnly Property DarkDarkPen() As Pen
            Get
                Return m_penDarkDark
            End Get
        End Property
        Public ReadOnly Property LightPen() As Pen
            Get
                Return m_penLight
            End Get
        End Property
        Public ReadOnly Property LightLightPen() As Pen
            Get
                Return m_penLightLight
            End Get
        End Property


        Public Shared ReadOnly Property OneLineFormat() As StringFormat
            Get
                format.Alignment = StringAlignment.Center
                format.LineAlignment = StringAlignment.Center
                format.Trimming = StringTrimming.EllipsisCharacter
                format.FormatFlags = StringFormatFlags.LineLimit
                format.HotkeyPrefix = HotkeyPrefix.Show

                Return format
            End Get
        End Property

        Public Shared ReadOnly Property OneLineNoTrimming() As StringFormat
            Get
                format.Alignment = StringAlignment.Center
                format.LineAlignment = StringAlignment.Center
                format.Trimming = StringTrimming.None
                format.FormatFlags = StringFormatFlags.LineLimit
                format.HotkeyPrefix = HotkeyPrefix.Show

                Return format
            End Get
        End Property
#End Region

#Region "Initialize/Finilize functions"
        ''' <summary>
        ''' Default Constructor 
        ''' </summary>
        Public Sub New()
            Me.Dark = SystemColors.ControlDark
            Me.DarkDark = SystemColors.ControlDarkDark
            Me.Light = SystemColors.ControlLight
            Me.LightLight = SystemColors.ControlLightLight
        End Sub

        ''' <summary>
        ''' Constructor used to override default colors used by class
        ''' </summary>
        Public Sub New(ByVal Dark As Color, ByVal DarkDark As Color, ByVal Light As Color, ByVal LightLight As Color)
            Me.Dark = Dark
            Me.DarkDark = DarkDark
            Me.Light = Light
            Me.LightLight = LightLight
        End Sub

        ''' <summary>
        ''' Destroy all pens and brushes used by class
        ''' </summary>
        Public Sub Dispose()
            If Not m_brushDark Is Nothing Then
                m_brushDark.Dispose()
            End If
            If Not m_penDark Is Nothing Then
                m_penDark.Dispose()
            End If
            If Not m_brushDarkDark Is Nothing Then
                m_brushDarkDark.Dispose()
            End If
            If Not m_penDarkDark Is Nothing Then
                m_penDarkDark.Dispose()
            End If
            If Not m_brushLight Is Nothing Then
                m_brushLight.Dispose()
            End If
            If Not m_penLight Is Nothing Then
                m_penLight.Dispose()
            End If
            If Not m_brushLightLight Is Nothing Then
                m_brushLightLight.Dispose()
            End If
            If Not m_penLightLight Is Nothing Then
                m_penLightLight.Dispose()
            End If
        End Sub

#End Region

#Region "Custom Drawing functions"
        ''' <summary>
        ''' Draw 3d Line. 3D Line is a simple line wich contains one dark and one light line.
        ''' By dark and light line we create optical 3D effect.
        ''' </summary>
        ''' <param name="graph">Graphics object which used by function to draw</param>
        ''' <param name="pnt1">Start System.Drawing.Point</param>
        ''' <param name="pnt2">End System.Drawing.Point</param>
        Public Sub Draw3DLine(ByVal graph As Graphics, ByVal pnt1 As System.Drawing.Point, ByVal pnt2 As System.Drawing.Point)
            Dim penDark As Pen = New Pen(m_brushDark)
            Dim penLight As Pen = New Pen(m_brushLightLight)

            Dim arrPoint As System.Drawing.Point() = {pnt1, pnt2}   ' create copy of System.Drawing.Point input params
            graph.DrawLine(penLight, pnt1, pnt2) ' draw first line

            If pnt1.X = pnt2.X Then
                arrPoint(0).X -= 1
                arrPoint(1).X -= 1
            ElseIf pnt1.Y = pnt2.Y Then
                arrPoint(0).Y -= 1
                arrPoint(1).Y -= 1
            Else
                arrPoint(0).X -= 1
                arrPoint(0).Y -= 1
                arrPoint(1).X -= 1
                arrPoint(1).Y -= 1
            End If

            graph.DrawLine(penDark, arrPoint(0), arrPoint(1))

            penDark.Dispose()
            penLight.Dispose()
        End Sub

        ''' <summary>
        ''' Draw 3D box according to style specification. There are four styles which our
        ''' function know how to draw.
        ''' </summary>
        ''' <param name="graph">Graphics object used for drawing</param>
        ''' <param name="rect">Box rectangle</param>
        ''' <param name="style">Style of Box</param>
        Public Sub Draw3DBox(ByVal graph As Graphics, ByVal rect As Rectangle, ByVal style As Canvas3DStyle)
            Dim pnt1 As System.Drawing.Point = System.Drawing.Point.Empty, pnt2 As System.Drawing.Point = System.Drawing.Point.Empty, pnt4 As System.Drawing.Point = System.Drawing.Point.Empty
            Dim arrPoints As System.Drawing.Point() = {pnt1, pnt2, pnt1, pnt4}

            Select Case style
                Case Canvas3DStyle.Flat
                    graph.DrawRectangle(m_penDark, rect)

                Case Canvas3DStyle.Title

                    graph.DrawRectangle(m_penDark, rect)

                    pnt1.X = rect.X + 1
                    pnt1.Y = rect.Y + 1
                    pnt2.X = rect.X + 1
                    pnt2.Y = rect.Height - 1
                    pnt4.X = rect.Width - 1
                    pnt4.Y = rect.Y + 1



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penLightLight, arrPoints)


                Case Canvas3DStyle.Raised

                    ' draw left upper corner
                    pnt1.X = rect.X
                    pnt1.Y = rect.Y
                    pnt2.X = rect.X + rect.Width
                    pnt2.Y = rect.Y
                    pnt4.X = rect.X
                    pnt4.Y = rect.Y + rect.Height



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penDark, arrPoints)

                    pnt1.X += 1
                    pnt1.Y += 1
                    pnt2.X -= 2
                    pnt2.Y += 1
                    pnt4.X += 1
                    pnt4.Y -= 2



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penDarkDark, arrPoints)

                    pnt1.X = rect.X + rect.Width
                    pnt1.Y = rect.Y + rect.Height
                    pnt2.X = rect.X
                    pnt2.Y = rect.Y + rect.Height
                    pnt4.X = rect.X + rect.Width
                    pnt4.Y = rect.Y



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penLightLight, arrPoints)

                    pnt1.X -= 1
                    pnt1.Y -= 1
                    pnt2.X += 1
                    pnt2.Y -= 1
                    pnt4.X -= 1
                    pnt4.Y += 1



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penLight, arrPoints)


                Case Canvas3DStyle.Upped

                    ' draw left upper corner
                    pnt1.X = rect.X
                    pnt1.Y = rect.Y
                    pnt2.X = rect.X + rect.Width
                    pnt2.Y = rect.Y
                    pnt4.X = rect.X
                    pnt4.Y = rect.Y + rect.Height



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penLightLight, arrPoints)

                    pnt1.X += 1
                    pnt1.Y += 1
                    pnt2.X -= 2
                    pnt2.Y += 1
                    pnt4.X += 1
                    pnt4.Y -= 2



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penLight, arrPoints)

                    pnt1.X = rect.X + rect.Width
                    pnt1.Y = rect.Y + rect.Height
                    pnt2.X = rect.X
                    pnt2.Y = rect.Y + rect.Height
                    pnt4.X = rect.X + rect.Width
                    pnt4.Y = rect.Y



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penDarkDark, arrPoints)

                    pnt1.X -= 1
                    pnt1.Y -= 1
                    pnt2.X += 1
                    pnt2.Y -= 1
                    pnt4.X -= 1
                    pnt4.Y += 1



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penDark, arrPoints)


                Case Canvas3DStyle.Single

                    ' draw left upper corner
                    pnt1.X = rect.X
                    pnt1.Y = rect.Y
                    pnt2.X = rect.Width
                    pnt2.Y = rect.Y
                    pnt4.X = rect.X
                    pnt4.Y = rect.Height



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penDark, arrPoints)

                    ' draw right low corner
                    pnt1.X = rect.Width
                    pnt1.Y = rect.Height
                    pnt2.X = rect.X
                    pnt2.Y = rect.Height
                    pnt4.X = rect.Width
                    pnt4.Y = rect.Y



                    arrPoints(0) = pnt1
                    arrPoints(2) = pnt1
                    arrPoints(1) = pnt2
                    arrPoints(3) = pnt4

                    graph.DrawLines(m_penLightLight, arrPoints)

            End Select
        End Sub

        ''' <summary>
        ''' Draw Active rectangle by blue colors
        ''' </summary>
        ''' <param name="graph">Graphic context where premitive must be draw</param>
        ''' <param name="rect">Destination Rectangle</param>
        ''' <param name="state">State of rectangle. Influence on colors by which rectangle
        ''' will be drawed</param>
        Public Sub DrawActiveRectangle(ByVal graph As Graphics, ByVal rect As Rectangle, ByVal state As HightlightStyle)
            Dim highlight As Color = IIf((state = HightlightStyle.Active), ColorUtil.VSNetBackgroundColor, ColorUtil.VSNetSelectionColor)
            '		Color.FromArgb( 182, 189, 210 ) : Color.FromArgb(212,213,216);

            Dim highBorder As Color = SystemColors.Highlight
            'Color.FromArgb( 10, 36, 106 );

            Dim high As SolidBrush = New SolidBrush(highlight)
            Dim bord As SolidBrush = New SolidBrush(highBorder)
            Dim penBord As Pen = New Pen(bord)

            graph.FillRectangle(high, rect)
            graph.DrawRectangle(penBord, rect)

            penBord.Dispose()
            bord.Dispose()
            high.Dispose()
        End Sub

        ''' <summary>
        ''' Draw Active rectangle.
        ''' </summary>
        ''' <param name="graph">Graphic context where premitive must be draw</param>
        ''' <param name="rect">Destination Rectangle</param>
        ''' <param name="state">State of rectangle. Influence on colors by which rectangle
        ''' will be drawed</param>
        ''' <param name="bSubRect">Indicate do we need rectangle width and height fix</param>
        Public Sub DrawActiveRectangle(ByVal graph As Graphics, ByVal rect As Rectangle, ByVal state As HightlightStyle, ByVal bSubRect As Boolean)
            Dim rc As Rectangle = IIf((bSubRect), FixRectangleHeightWidth(rect), rect)
            DrawActiveRectangle(graph, rc, state)
        End Sub

        ''' <summary>
        ''' Make rectangle width and height less on one pixel. This useful beacause
        ''' in some cases rectangle last pixels does not shown.
        ''' </summary>
        ''' <param name="rect">Rectangle which context must be fixed</param>
        ''' <returns>Return new Rectangle object which contains fixed values</returns>
        Public Shared Function FixRectangleHeightWidth(ByVal rect As Rectangle) As Rectangle
            Return New Rectangle(rect.X, rect.Y, rect.Width - 1, rect.Height - 1)
        End Function
#End Region

#Region "Class Helper Functions"
        ''' <summary>
        ''' Calculate X and Y coordiante to place object in center of Rectangle
        ''' </summary>
        ''' <param name="rect">Destination Rectangle</param>
        ''' <param name="sz">Object Size</param>
        ''' <returns>Point class with X and Y coordinate of center</returns>
        Public Shared Function CalculateCenter(ByVal rect As Rectangle, ByVal sz As System.Drawing.Size) As System.Drawing.Point
            Dim pnt1 As System.Drawing.Point = New System.Drawing.Point(0)

            pnt1.X = rect.X + (rect.Width - sz.Width) / 2
            pnt1.Y = rect.Y + (rect.Height - sz.Height) / 2

            Return pnt1
        End Function

#End Region

#Region "Methods"
        ''' <summary>
        ''' Draw 3D styled Rectangle. 
        ''' </summary>
        ''' <param name="g">Graphics canvas where rectangle must drawed</param>
        ''' <param name="rc">Rectangle coordinates</param>
        ''' <param name="clrTL">Color of Top Left corner of rectangle</param>
        ''' <param name="clrBR">Color of Bottom Right corner of rectangle</param>
        Public Shared Sub Draw3DRect(ByVal g As Graphics, ByVal rc As Rectangle, ByVal clrTL As Color, ByVal clrBR As Color)
            Draw3DRect(g, rc.Left, rc.Top, rc.Width, rc.Height, clrTL, clrBR)
        End Sub

        Public Shared Sub Draw3DRect(ByVal g As Graphics, ByVal x As Integer, ByVal y As Integer, ByVal width As Integer, ByVal height As Integer, ByVal clrTL As Color, ByVal clrBR As Color)
            'INSTANT VB NOTE: The following 'using' block is replaced by its pre-VB.NET 2005 equivalent:
            '			using(Brush brushTL = New SolidBrush(clrTL))
            Dim brushTL As Brush = New SolidBrush(clrTL)
            Try
                'INSTANT VB NOTE: The following 'using' block is replaced by its pre-VB.NET 2005 equivalent:
                '				using(Brush brushBR = New SolidBrush(clrBR))
                Dim brushBR As Brush = New SolidBrush(clrBR)
                Try
                    g.FillRectangle(brushTL, x, y, width - 1, 1)
                    g.FillRectangle(brushTL, x, y, 1, height - 1)
                    g.FillRectangle(brushBR, x + width, y, -1, height)
                    g.FillRectangle(brushBR, x, y + height, width, -1)
                Finally
                    If TypeOf brushBR Is IDisposable Then
                        Dim disp As IDisposable = brushBR
                        disp.Dispose()
                    End If
                End Try
                'INSTANT VB NOTE: End of the original C# 'using' block
            Finally
                If TypeOf brushTL Is IDisposable Then
                    Dim disp As IDisposable = brushTL
                    disp.Dispose()
                End If
            End Try
            'INSTANT VB NOTE: End of the original C# 'using' block
        End Sub

        Public Shared Sub StrechBitmap(ByVal gDest As Graphics, ByVal rcDest As Rectangle, ByVal bitmap As System.Drawing.Bitmap)

            ' Draw From bitmap
            Dim hDCTo As IntPtr = gDest.GetHdc()
            WindowsAPI.SetStretchBltMode(hDCTo, CInt(StrechModeFlags.HALFTONE))
            Dim hDCFrom As IntPtr = WindowsAPI.CreateCompatibleDC(hDCTo)

            Dim hOldFromBitmap As IntPtr = WindowsAPI.SelectObject(hDCFrom, bitmap.GetHbitmap())
            WindowsAPI.StretchBlt(hDCTo, rcDest.Left, rcDest.Top, rcDest.Width, rcDest.Height, hDCFrom, 0, 0, bitmap.Width, bitmap.Height, Convert.ToUInt32(PatBltTypes.SRCCOPY))

            ' Cleanup
            WindowsAPI.SelectObject(hDCFrom, hOldFromBitmap)
            gDest.ReleaseHdc(hDCTo)

        End Sub

        Public Shared Sub StrechBitmap(ByVal gDest As Graphics, ByVal rcDest As Rectangle, ByVal rcSource As Rectangle, ByVal bitmap As System.Drawing.Bitmap)

            ' Draw From bitmap
            Dim hDCTo As IntPtr = gDest.GetHdc()
            WindowsAPI.SetStretchBltMode(hDCTo, CInt(StrechModeFlags.COLORONCOLOR))
            Dim hDCFrom As IntPtr = WindowsAPI.CreateCompatibleDC(hDCTo)

            Dim hOldFromBitmap As IntPtr = WindowsAPI.SelectObject(hDCFrom, bitmap.GetHbitmap())
            WindowsAPI.StretchBlt(hDCTo, rcDest.Left, rcDest.Top, rcDest.Width, rcDest.Height, hDCFrom, rcSource.Left, rcSource.Top, rcSource.Width, rcSource.Height, Convert.ToUInt32(PatBltTypes.SRCCOPY))

            ' Cleanup
            WindowsAPI.SelectObject(hDCFrom, hOldFromBitmap)
            gDest.ReleaseHdc(hDCTo)

        End Sub

        Public Shared Function GetStrechedBitmap(ByVal gDest As Graphics, ByVal rcDest As Rectangle, ByVal bitmap As System.Drawing.Bitmap) As System.Drawing.Bitmap

            ' Draw To bitmap
            Dim newBitmap As System.Drawing.Bitmap = New System.Drawing.Bitmap(rcDest.Width, rcDest.Height)
            Dim gBitmap As Graphics = Graphics.FromImage(newBitmap)
            Dim hDCTo As IntPtr = gBitmap.GetHdc()
            WindowsAPI.SetStretchBltMode(hDCTo, CInt(StrechModeFlags.COLORONCOLOR))
            Dim hDCFrom As IntPtr = WindowsAPI.CreateCompatibleDC(hDCTo)

            Dim hOldFromBitmap As IntPtr = WindowsAPI.SelectObject(hDCFrom, bitmap.GetHbitmap())
            WindowsAPI.StretchBlt(hDCTo, rcDest.Left, rcDest.Top, rcDest.Width, rcDest.Height, hDCFrom, 0, 0, bitmap.Width, bitmap.Height, Convert.ToUInt32(PatBltTypes.SRCCOPY))

            ' Cleanup
            WindowsAPI.SelectObject(hDCFrom, hOldFromBitmap)
            gBitmap.ReleaseHdc(hDCTo)

            Return newBitmap
        End Function

        Public Shared Function GetTileBitmap(ByVal rcDest As Rectangle, ByVal bitmap As System.Drawing.Bitmap) As System.Drawing.Bitmap

            Dim tiledBitmap As System.Drawing.Bitmap = New System.Drawing.Bitmap(rcDest.Width, rcDest.Height)
            'INSTANT VB NOTE: The following 'using' block is replaced by its pre-VB.NET 2005 equivalent:
            '			using(Graphics g = Graphics.FromImage(tiledBitmap))
            Dim g As Graphics = Graphics.FromImage(tiledBitmap)
            Try
                For i As Integer = 0 To tiledBitmap.Width - 1 Step bitmap.Width
                    For j As Integer = 0 To tiledBitmap.Height - 1 Step bitmap.Height
                        g.DrawImage(bitmap, New System.Drawing.Point(i, j))
                    Next j
                Next i
            Finally
                If TypeOf g Is IDisposable Then
                    Dim disp As IDisposable = g
                    disp.Dispose()
                End If
            End Try
            'INSTANT VB NOTE: End of the original C# 'using' block

            Return tiledBitmap
        End Function

        Public Shared Sub DrawArrowGlyph(ByVal g As Graphics, ByVal rc As Rectangle, ByVal up As Boolean, ByVal brush As Brush)
            ' Draw arrow glyph with the default size of 5 pixel wide and 3 pixel high
            DrawArrowGlyph(g, rc, 5, 3, up, brush)
        End Sub

        Public Shared Sub DrawArrowGlyph(ByVal g As Graphics, ByVal rc As Rectangle, ByVal arrowWidth As Integer, ByVal arrowHeight As Integer, ByVal up As Boolean, ByVal brush As Brush)

            ' TIP: use an odd number for the arrowWidth and 
            ' arrowWidth/2+1 for the arrowHeight 
            ' so that the arrow gets the same pixel number
            ' on the left and on the right and get symetrically painted
            Dim pts As System.Drawing.Point() = New System.Drawing.Point(2) {}
            Dim yMiddle As Integer = rc.Top + rc.Height / 2 - arrowHeight / 2 + 1
            Dim xMiddle As Integer = rc.Left + rc.Width / 2
            Dim yArrowHeight As Integer = yMiddle + arrowHeight
            Dim xArrowWidthR As Integer = xMiddle + arrowWidth / 2
            Dim xArrowWidthL As Integer = xMiddle - arrowWidth / 2

            If up Then
                pts(0) = New System.Drawing.Point(xMiddle, yMiddle - 2)
                pts(1) = New System.Drawing.Point(xArrowWidthL - 1, yArrowHeight - 1)
                pts(2) = New System.Drawing.Point(xArrowWidthR + 1, yArrowHeight - 1)

            Else
                pts(0) = New System.Drawing.Point(xArrowWidthL, yMiddle)
                pts(1) = New System.Drawing.Point(xArrowWidthR + 1, yMiddle)
                pts(2) = New System.Drawing.Point(xMiddle, yArrowHeight)
            End If

            g.FillPolygon(brush, pts)
        End Sub

#End Region
    End Class
End Namespace
